#pragma once

#include "Common.hpp"

#define CONV(addr) ((struct sockaddr *)&addr) // 各socketaddr结构体类型 -> sockaddr *类型地址

class InetAddr
{
public:
    // 构造函数0 , 无参构造
    InetAddr() {}

    // 构造函数1.1, 网络序列格式地址 -> 主机序列格式地址
    void SetAddr(struct sockaddr_in addr)
    {
        _addr = addr; // 获取网络序列地址
        // _ip = inet_ntoa(_addr.sin_addr); // 获取IP地址
        char ipbuffer[64];                                            // 临时缓冲区, 用于临时存放IP地址
        inet_ntop(AF_INET, &_addr.sin_addr, ipbuffer, sizeof(_addr)); // 将网络字节序的二进制格式 -> 点分十进制字符串格式, _addr.sin_addr -> ipbuffer
        _ip = ipbuffer;                                               // IP地址成员赋值
        _port = ntohs(_addr.sin_port);                                // 获取端口号
    }

    // 构造函数1.2 , 网络序列格式地址 -> 主机序列格式地址
    InetAddr(struct sockaddr_in addr)
    {
        SetAddr(addr);
    }

    // 构造函数2 , 主机序列格式地址 -> 网络序列格式地址
    InetAddr(const std::string &ip, uint16_t port) : _ip(ip), _port(port)
    {
        memset(&_addr, 0, sizeof(_addr)); // _addr初始化

        _addr.sin_family = AF_INET;                      // 设置地址族为IPv4
        inet_pton(AF_INET, ip.c_str(), &_addr.sin_addr); // 设置IP地址, 将点分十进制字符串格式 -> 网络字节序的二进制格式, ip -> _addr.sin_addr
        _addr.sin_port = htons(port);                    // 设置端口号, 主机字节序 -> 网络字节序, port -> _addr.sin_port
    }

    // 构造函数3 , 主机序列格式地址 -> 网络序列格式地址, 传参只包含port端口号, 默认ip为0
    InetAddr(uint16_t port) : _ip(), _port(port)
    {
        memset(&_addr, 0, sizeof(_addr)); // _addr初始化

        _addr.sin_family = AF_INET;         // 设置地址族为IPv4
        _addr.sin_addr.s_addr = INADDR_ANY; // 设置IP地址为0.0.0.0, 用于接收所有IP地址的连接请求
        _addr.sin_port = htons(port);       // 设置端口号, 主机字节序 -> 网络字节序, port -> _addr.sin_port
    }

    

    // 获取IP地址
    std::string getIp() const { return _ip; }

    // 获取端口号
    uint16_t getPort() const { return _port; }

    // 获取字符串形式的地址, 格式为[127.0.0.1 : 8080]
    std::string StringAddr()
    {
        return "[" + _ip + ":" + std::to_string(_port) + "]";
    }

    // 获取网络序列地址
    const struct sockaddr_in &getAddr() const { return _addr; }

    // 获取网络地址结构体地址
    const struct sockaddr *NetAddrPtr()
    {
        return CONV(_addr); // CONV宏, 返回网络地址结构体地址
        // return (const struct sockaddr *)&_addr;
    }

    // 获取网络地址结构体长度
    socklen_t NetAddrLen()
    {
        return sizeof(_addr);
    }

    // ==运算符重载, 比较两个InetAddr对象是否相等
    bool operator==(const InetAddr &addr)
    {
        return addr._ip == _ip && addr._port == _port;
    }

    // 析构函数
    ~InetAddr()
    {
    }

private:
    struct sockaddr_in _addr; // 网络序列
    std::string _ip;          // ip地址
    uint16_t _port;           // 端口号
};
